package com.alibaba.dongbao.service.impl;

import com.alibaba.dongbao.base.Code.CodeMsg;
import com.alibaba.dongbao.base.result.Result;
import com.alibaba.dongbao.dto.UserDTO;
import com.alibaba.dongbao.entity.User;
import com.alibaba.dongbao.mapper.UserMapper;
import com.alibaba.dongbao.service.UserService;
import com.alibaba.dongbao.utils.PwdCheckUtil;
import com.alibaba.dongbao.utils.jwt.JwtUtil;
import com.alibaba.dongbao.utils.MapSortUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserMapper memberMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * @Author: Mr.ZJW
     * @Description: 用户注册
     * @Date: 2022/4/6 17:11
     **/
    @Override
    public Result registerUser(User member) {
        if (ObjectUtils.isEmpty(member)) {
            return Result.error(CodeMsg.PARAMETER_ISNULL);
        }
        //判断是否用户名重复
        User user = memberMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, member.getUsername()));
        if (ObjectUtils.isNotEmpty(user)) {
            return Result.error("用户名重复，请重新输入!");
        }
        //进行BCryptPasswordEncoder加密密码
        String encode = passwordEncoder.encode(member.getPassword());
        member.setPassword(encode);
        //添加
        int insert = memberMapper.insert(member);
        if (insert <= 0) {
            return Result.error(CodeMsg.REGISTER_ERROR);
        }
        return Result.success(CodeMsg.REGISTER_SUCCESS);
    }

    /**
     * @param memberDTO
     * @Author: Mr.ZJW
     * @Description: 登录
     * @Date: 2022/4/7 14:50
     */
    @Override
    public Result login(UserDTO memberDTO) {
        if (null == memberDTO.getCode()) {
            return Result.error("请输入验证码!");
        }
        //判断用户名密码
        User user = memberMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, memberDTO.getUsername()));
        //从Redis获取验证码
        String code = redisTemplate.opsForValue().get("code");
        //解析验证码
        if (memberDTO.getCode().equals(code)) {
            if (ObjectUtils.isNotEmpty(user) && passwordEncoder.matches(memberDTO.getPassword(), user.getPassword())) {
                //删除验证码
                redisTemplate.delete("code");
                //生成Token
                String token = JwtUtil.createToken(memberDTO.getUsername());
                //更新登录时间
                LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(User::getUsername, user.getUsername());
                wrapper.set(User::getLoginTime, new Date());
                update(wrapper);
                //存放Token以及用户信息
                HashMap<String, Object> map = new HashMap<>();
                map.put("Token", token);
                map.put("User", user);
                //排序
                Map<String, Object> stringObjectMap = MapSortUtil.sortMapByKey(map);
                return Result.success("登录成功", stringObjectMap);
            }
        } else {
            return Result.error(CodeMsg.LOGIN_ERROR_CODE);
        }
        return Result.error(CodeMsg.LOGIN_ERROR_PASS);
    }

    /**
     * @Author: Mr.ZJW
     * @Description: 查询用户列表
     * @Date: 2022/4/8 14:01
     **/
    @Override
    public IPage<User> queryUserList(Page page, UserDTO member) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(member.getUsername()), User::getUsername, member.getUsername());
        wrapper.like(StringUtils.isNotBlank(member.getName()), User::getName, member.getName());
        wrapper.like(StringUtils.isNotBlank(member.getPhone()), User::getPhone, member.getPhone());
        wrapper.like(StringUtils.isNotBlank(member.getNickName()), User::getNickName, member.getNickName());
        //根据创建时间范围查询
        wrapper.ge(StringUtils.isNotBlank(member.getStartTime()), User::getGmtCreate, member.getStartTime() + " 00:00:00")
                .le(StringUtils.isNotBlank(member.getEndTime()), User::getGmtCreate, member.getEndTime() + " 23:59:59");
        wrapper.orderByAsc(User::getGmtModified);
        return memberMapper.selectPage(page, wrapper);
    }

    /**
     * @param user
     * @Author: Mr.ZJW
     * @Description: 修改用户信息
     * @Date: 2022/4/8 16:11
     */
    @Override
    public Result modifyUser(User user) {
        //判断对象是否为空
        if (ObjectUtils.isEmpty(user)) {
            return Result.error(CodeMsg.PARAMETER_ISNULL);
        }
        int i = memberMapper.updateById(user);
        if (i <= 0) {
            return Result.error(CodeMsg.UPDATE_ERROR);
        }
        return Result.success(CodeMsg.UPDATE_SUCCESS);
    }

    /**
     * @param [user]
     * @param userDTO
     * @Author: Mr.ZJW
     * @Description: 用户修改密码
     * @Date: 2022/6/6 9:09
     **/
    @Override
    public Result userModifyPassword(UserDTO userDTO) {
        //判断对象是否为空
        if (ObjectUtils.isEmpty(userDTO)) {
            return Result.error(CodeMsg.PARAMETER_ISNULL);
        }
        //判断密码是否包含数字+字母+字符
        if (false == PwdCheckUtil.checkContainDigit(userDTO.getOnePassword())
                || false == PwdCheckUtil.checkContainCase(userDTO.getOnePassword())
                || false == PwdCheckUtil.checkContainSpecialChar(userDTO.getOnePassword())){
            return Result.error(CodeMsg.PASSWORD_INCLUDE_ENGLISH_NUMBER_SYMBOL);
        }
        //根据用户ID查询用户信息
        User userInfo = memberMapper.selectById(userDTO.getUserId());
        //判断用户输出的原始密码是否正确
        boolean matches = passwordEncoder.matches(userDTO.getPassword(), userInfo.getPassword());
        //判断旧密码和输入的新密码是否一致，如果一致不允许修改
        boolean oneMatches = passwordEncoder.matches(userDTO.getOnePassword(), userInfo.getPassword());
        boolean againMatchesNew = passwordEncoder.matches(userDTO.getAgainPassword(), userInfo.getPassword());
        //如果正确才允许修改新密码
        if (true == matches) {
            //判断第一次与第二次密码是否一致
            if (userDTO.getOnePassword().equals(userDTO.getAgainPassword())) {
                //判断旧密码和输入的新密码是否一致
                if (false == oneMatches || false == againMatchesNew) {
                    //进行加密
                    String encodePassword = passwordEncoder.encode(userDTO.getOnePassword());
                    //更新
                    LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
                    wrapper.eq(User::getUserId, userDTO.getUserId())
                            .set(User::getPassword, encodePassword);
                    int update = memberMapper.update(null, wrapper);
                    if (update <= 0) {
                        return Result.error(CodeMsg.UPDATE_ERROR);
                    }
                    return Result.success(CodeMsg.UPDATE_SUCCESS);
                }
                return Result.error(CodeMsg.OLD_PASSWORD_LIKE_NEW_PASSWORD);
            }
            return Result.error(CodeMsg.NEW_PASSWORD_UNLIKE);
        }
        return Result.error(CodeMsg.ORIGINAL_PASSWORD_ERROR);
    }

}
